from django.shortcuts import render
from rest_framework.views import APIView
from QQLoginTool.QQtool import OAuthQQ
from rest_framework.response import Response
from django.conf import settings
from rest_framework import status
from rest_framework_jwt.settings import api_settings
from rest_framework.mixins import CreateModelMixin

from .models import OAuthQQUser
from .utils import generate_save_user_token, generate_token
from .serializers import QQAuthUserSerializer
from carts.utils import merge_cart_cookie_to_redis


# Create your views here.
"""
当用户在前端登录界面点击 QQ登录按钮向后端发送请求 (获取QQ登录扫码url)
"""

class QQAuthURLView(APIView):

    def get(self, request):
        # request.query_params

        # 提取前端通过查询参数传入的next(记录用来从那里跳转到登录)
        next = request.query_params.get('next')
        if next is None:
            next = '/'


        # 利用QQ登录SDK
        # oAuth = OAuthQQ(client_id=appid, client_secret=appkey, redirect_uri=回调url, state=从那里来到登录界面来源路径)
        oAuth = OAuthQQ(client_id=settings.QQ_CLIENT_ID,
                        client_secret=settings.QQ_CLIENT_SECRET,
                        redirect_uri=settings.QQ_REDIRECT_URI,
                        state=next)
        # 调用SDK中的方法获取拼接好的扫码登录url
        login_url = oAuth.get_qq_url()
        # 响应扫码登录url
        return Response({'login_url': login_url})


class QQAuthUserView(APIView):
    """QQ扫码登录成功后的回调处理"""

    def get(self, request):
        # 提前查询参数中的code
        code = request.query_params.get('code')
        # 如果code没有提取到提前响应400
        if code is None:
            return Response({'message': 'code无效'}, status=status.HTTP_400_BAD_REQUEST)

        # 创建QQ登录工具对象
        oAuth = OAuthQQ(client_id=settings.QQ_CLIENT_ID,
                        client_secret=settings.QQ_CLIENT_SECRET,
                        redirect_uri=settings.QQ_REDIRECT_URI)
        try:
            # 向QQ服务器发请求 用code获取access token
            access_token = oAuth.get_access_token(code)

            # 再次向QQ服务器发请求 用access token 获取openid
            openid = oAuth.get_open_id(access_token)
        except Exception as error:
            return Response({'message': 'QQ服务器异常'}, status=status.HTTP_503_SERVICE_UNAVAILABLE)


        try:
            # 用openid去查询OAuthQQUser表中是否用这个openid
            oAuth_model = OAuthQQUser.objects.get(openid=openid)

        except OAuthQQUser.DoesNotExist:
            # 如果没有查到此openid,说明此openid 没有绑定过美多商城用户, 如果没有绑定过,创建一个新的美多用户,和此openid绑定
            # 对于没有绑定用户的openid 怎么办?
            # 对openid 进行加密
            openid_sign = generate_save_user_token(openid)
            # 响应时字典的key 由于前端提前写死了 access_token 变量,所以key 要用access_token
            return Response({'access_token': openid_sign})

        else:
            # 如果能查到openid,说明此openid 已经绑定过美多商城中的用户
            # 直接生成JWT token 响应回去,直接代表用户登录成功
            """
            jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER  # 加载生成载荷函数
            jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER  # 加载生成token的函数

            user = oAuth_model.user  # 直接通过外键获取到openid 绑定的用户
            payload = jwt_payload_handler(user)  # 通过传入user对象生成jwt 载荷部分
            token = jwt_encode_handler(payload)  # 传入payload 生成token
            """
            user = oAuth_model.user
            token = generate_token(user)
            #  QQ登录成功
            response = Response({
                'user_id': user.id,
                'username': user.username,
                'token': token
            })
            # 购物车合并
            merge_cart_cookie_to_redis(request, user, response)

            return response

    def post(self, request):
        """用openid 绑定美多商城用户"""
        # 1. 创建序列化器进行反序列化
        serializer = QQAuthUserSerializer(data=request.data)
        # 2. 调用序列化的校验方法
        serializer.is_valid(raise_exception=True)
        # 3. 调用序列化器的save 新增数据
        user = serializer.save()  # 序列化器中的create方法或update方法的返回值会作为序列化器save方法的返回值
        # 4.生成JWT token
        token = generate_token(user)
        # merge_cart_cookie_to_redis(dict1)
        # QQ 登录成功
        response = Response({
            'user_id': user.id,
            'username': user.username,
            'token': token
        })
        # 购物车合并
        merge_cart_cookie_to_redis(request, user, response)
        # 5.响应
        return response
